package io.wongxd.solution.util.asyncTask

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import io.wongxd.solution.util.coroutine.CoroutineTaskHelper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
 *
 * 简易的AsyncTask类。内部为线程池或者协程实现
 *
 * Simple async task
 *
 * @constructor Create empty Simple async task
 */
object SimpleAsyncTask {

    private val coroutineTask by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { CoroutineTaskHelper.newTask() }

    /////////////////////////////////////////////////////////////  基于线程池实现  ///////////////////////////////////////////////////////////////////

    fun <E> run(lifecycle: Lifecycle, backgroundTask: BackgroundTask<E>, foregroundTask: ForegroundTask<E>) {
        if (!isValid(lifecycle)) return
        ThreadUtils.postTaskIoThread {
            val result = backgroundTask.run()
            if (!isValid(lifecycle)) return@postTaskIoThread
            ThreadUtils.runTaskMainThread { if (isValid(lifecycle)) foregroundTask.run(result) }
        }
    }

    fun <E> run(lifecycleOwner: LifecycleOwner, backgroundTask: BackgroundTask<E>, foregroundTask: ForegroundTask<E>) {
        if (!isValid(lifecycleOwner.lifecycle)) return
        ThreadUtils.postTaskIoThread {
            val result = backgroundTask.run()
            if (!isValid(lifecycleOwner.lifecycle)) return@postTaskIoThread
            ThreadUtils.runTaskMainThread { if (isValid(lifecycleOwner.lifecycle)) foregroundTask.run(result) }
        }
    }

    fun <E> run(backgroundTask: BackgroundTask<E>, foregroundTask: ForegroundTask<E>) {
        ThreadUtils.postTaskIoThread {
            val result = backgroundTask.run()
            ThreadUtils.runTaskMainThread { foregroundTask.run(result) }
        }
    }

    fun <E> run(delay: Long, backgroundTask: BackgroundTask<E>, foregroundTask: ForegroundTask<E>) {
        ThreadUtils.postTaskIoThread {
            val result = backgroundTask.run()
            ThreadUtils.postTaskMainThreadDelay(delay) { foregroundTask.run(result) }
        }
    }

    /////////////////////////////////////////////////////////////  基于协程实现  ///////////////////////////////////////////////////////////////////

    fun <E> run(lifecycle: Lifecycle, backgroundTask: () -> E, foregroundTask: (E) -> Unit) {
        if (!isValid(lifecycle)) return
        coroutineTask.runIoThread {
            val result = backgroundTask.invoke()
            if (!isValid(lifecycle)) return@runIoThread
            withContext(Dispatchers.Main) { foregroundTask.invoke(result) }
        }
    }

    fun <E> run(lifecycleOwner: LifecycleOwner, backgroundTask: () -> E, foregroundTask: (E) -> Unit) {
        if (!isValid(lifecycleOwner.lifecycle)) return
        coroutineTask.runIoThread {
            val result = backgroundTask.invoke()
            if (!isValid(lifecycleOwner.lifecycle)) return@runIoThread
            withContext(Dispatchers.Main) { foregroundTask.invoke(result) }
        }
    }

    fun <E> run(backgroundTask: () -> E, foregroundTask: (E) -> Unit) {
        coroutineTask.runIoThread {
            val result = backgroundTask.invoke()
            withContext(Dispatchers.Main) { foregroundTask.invoke(result) }
        }
    }

    fun <E> runSuspend(lifecycle: Lifecycle, background: CoroutineScope.() -> E, foreground: CoroutineScope.(E) -> Unit) {
        if (!isValid(lifecycle)) return
        coroutineTask.runIoThread {
            val result = background()
            if (!isValid(lifecycle)) return@runIoThread
            withContext(Dispatchers.Main) { foreground(result) }
        }
    }

    fun <E> runSuspend(
        lifecycleOwner: LifecycleOwner,
        background: CoroutineScope.() -> E,
        foreground: CoroutineScope.(E) -> Unit
    ) {
        if (!isValid(lifecycleOwner.lifecycle)) return
        coroutineTask.runIoThread {
            val result = background()
            if (!isValid(lifecycleOwner.lifecycle)) return@runIoThread
            withContext(Dispatchers.Main) { foreground(result) }
        }
    }

    fun <E> runSuspend(background: CoroutineScope.() -> E, foreground: CoroutineScope.(E) -> Unit) {
        coroutineTask.runIoThread {
            val result = background()
            withContext(Dispatchers.Main) { foreground(result) }
        }
    }

    private fun isValid(lifecycle: Lifecycle): Boolean {
        return lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)
    }
}
